package data

import (
	"context"
	"gorm.io/gorm"
	v1 "gitlab.cqcb.com/shangyou_mic/dscm-approve-api-pb/api/roses/v1"
	"time"

	"rosesservice/internal/biz"
)

type Common struct {
	db   *DB
	rbac *RbacSchema
}

func NewCommon(
	db *DB,
	rbac *RbacSchema,
) (biz.CommonRepo, error) {
	return &Common{
		db:   db,
		rbac: rbac,
	}, nil
}

func (s *Common) LoadSystemConfig(ctx context.Context, req *v1.LoadSystemConfigRequest) (*v1.LoadSystemConfigReply, error) {
	reply := &v1.LoadSystemConfigReply{}
	lists := make([]*SystemConfig, 0)
	err := s.db.DB().Model(&SystemConfig{}).WithContext(ctx).Find(&lists).Error
	if err != nil {
		return nil, err
	}
	length := len(lists)
	reply.Lists = make([]*v1.SystemConfig, 0, length)
	for _, v := range lists {
		tmp := &v1.SystemConfig{
			Id:        v.Id,
			CfgKey:    v.CfgKey,
			CfgVal:    v.CfgVal,
			Note:      v.Note,
			CreatedAt: v.CreatedAt,
			UpdatedAt: v.UpdatedAt,
		}
		reply.Lists = append(reply.Lists, tmp)
	}
	return reply, nil
}

func (s *Common) SaveSystemConfig(ctx context.Context, req *v1.SaveSystemConfigRequest) (*v1.SaveSystemConfigReply, error) {
	reply := &v1.SaveSystemConfigReply{}
	timestamp := time.Now().Unix()
	length := len(req.Lists)
	lists := make([]*v1.SystemConfig, 0, length)
	for _, v := range req.Lists {
		tmp := &v1.SystemConfig{
			Id:        v.Id,
			CfgKey:    v.CfgKey,
			CfgVal:    v.CfgVal,
			Note:      v.Note,
			CreatedAt: timestamp,
			UpdatedAt: timestamp,
		}
		lists = append(lists, tmp)
	}
	model := &SystemConfig{}
	err := s.db.DB().Transaction(func(tx *gorm.DB) error {
		err := tx.WithContext(ctx).Where("id > 0").Unscoped().Delete(model).Error
		if err != nil {
			return err
		}
		err = tx.WithContext(ctx).Table(model.TableName()).Create(lists).Error
		if err != nil {
			return err
		}
		return nil
	})
	if err != nil {
		return nil, err
	}
	return reply, nil
}

func (s *Common) SystemConfigLists(ctx context.Context, req *v1.SystemConfigListsRequest) (*v1.SystemConfigListsReply, error) {
	reply := &v1.SystemConfigListsReply{}
	lists := make([]*SystemConfig, 0)
	err := s.db.DB().Model(&SystemConfig{}).WithContext(ctx).Find(&lists).Error
	if err != nil {
		return nil, err
	}
	length := len(lists)
	reply.Data = make([]*v1.SystemConfig, 0, length)
	for _, v := range lists {
		tmp := &v1.SystemConfig{
			Id:        v.Id,
			CfgKey:    v.CfgKey,
			CfgVal:    v.CfgVal,
			Note:      v.Note,
			CreatedAt: v.CreatedAt,
			UpdatedAt: v.UpdatedAt,
		}
		reply.Data = append(reply.Data, tmp)
	}
	reply.StatusCode = 200
	reply.Message = "success"
	return reply, nil
}

func (s *Common) SystemConfigUpdate(ctx context.Context, req *v1.SystemConfigUpdateRequest) (*v1.SystemConfigUpdateReply, error) {
	reply := &v1.SystemConfigUpdateReply{}
	updates := make(map[string]any)
	if req.CfgVal != nil {
		updates["cfg_val"] = req.GetCfgVal()
	}
	if req.Note != nil {
		updates["note"] = req.GetNote()
	}
	if len(updates) == 0 {
		reply.StatusCode = 200
		reply.Message = "success"
		return reply, nil
	}
	updates["updated_at"] = time.Now().Unix()
	err := s.db.DB().Model(&SystemConfig{}).WithContext(ctx).Where("id = ?", req.Id).Updates(updates).Error
	if err != nil {
		return nil, err
	}
	reply.StatusCode = 200
	reply.Message = "success"
	return reply, nil
}

func (s *Common) TopicLists(ctx context.Context, req *v1.TopicListsRequest) (*v1.TopicListsReply, error) {
	reply := &v1.TopicListsReply{}
	reply.StatusCode = 200
	reply.Message = "success"
	db := s.db.DB()
	lists := make([]*Topic, 0)
	db.Model(&Topic{}).Order("id ASC").Find(&lists)
	length := len(lists)
	reply.Data = make([]*v1.Topic, 0, length)
	for _, v := range lists {
		tmp := &v1.Topic{
			Id:        v.Id,
			Title:     v.Title,
			Keyword:   v.Keyword,
			State:     v.State,
			CreatedAt: v.CreatedAt,
			TopicId:   v.TopicId,
		}
		reply.Data = append(reply.Data, tmp)
	}
	return reply, nil
}

func (s *Common) WechatLoginUserinfo(ctx context.Context, req *v1.WechatLoginUserinfoRequest) (*v1.WechatLoginUserinfoReply, error) {
	db := s.db.DB()
	users := make([]*User, 0)
	err := db.Table((&UserWechat{}).TableName()+" a").
		Joins("LEFT JOIN "+(&User{}).TableName()+" b on a.user_id = b.id").
		Where("a.openid = ?", req.Openid).
		Where("b.id is not null").
		Select("b.*").
		Limit(1).
		Find(&users).
		Error
	if err != nil {
		return nil, err
	}
	reply := &v1.WechatLoginUserinfoReply{
		Openid: req.Openid,
	}
	var user *User
	if len(users) == 0 {
		user = &User{
			Category:     1,
			State:        1,
			StateReason:  "正常",
			RowCreatedAt: RowCreatedAt{},
			RowUpdatedAt: RowUpdatedAt{},
		}
		timestamp := time.Now().Unix()
		user.CreatedAt = timestamp
		user.UpdatedAt = timestamp
		_ = db.Transaction(func(tx *gorm.DB) error {
			err = tx.Model(&User{}).Create(user).Error
			if err != nil {
				return err
			}
			userWechat := &UserWechat{}
			userWechat.Openid = req.Openid
			userWechat.Nickname = req.Nickname
			userWechat.Sex = int(req.Sex)
			userWechat.Province = req.Province
			userWechat.City = req.City
			userWechat.Country = req.Country
			userWechat.HeadImgURL = req.Headimgurl
			userWechat.UnionID = req.Unionid
			err = tx.Model(&UserWechat{}).Create(userWechat).Error
			if err != nil {
				return err
			}
			return nil
		})
		if err != nil {
			return nil, err
		}
	} else {
		user = users[0]
	}
	reply.User = &v1.User{
		Id:             user.Id,
		Category:       user.Category,
		Mobile:         user.Mobile,
		Username:       user.Username,
		Email:          user.Email,
		PasswordSalt:   user.PasswordSalt,
		Password:       user.Password,
		Integral:       user.Integral,
		RealName:       user.RealName,
		IdCardNo:       user.IdCardNo,
		BankNo:         user.BankNo,
		BankOpen:       user.BankOpen,
		Note:           user.Note,
		IsInternal:     int32(user.IsInternal),
		State:          user.State,
		StateReason:    user.StateReason,
		ReturnNormalAt: user.ReturnNormalAt,
		VersionId:      user.VersionId,
		CreatedAt:      user.CreatedAt,
		UpdatedAt:      user.UpdatedAt,
		DeletedAt:      user.DeletedAt,
		Level:          user.Level,
		LastFreezeAt:   user.LastFreezeAt,
		IsVerifier:     user.IsVerifier,
	}
	return reply, nil
}
